import { ipcMain } from "electron";
import child_process from "node:child_process";
import iconv from "iconv-lite";
import fs from "node:fs";
import { getAssetPath } from "@elec/main/util/assets.ts";

(() => {
  // Windows24H2新增了sudo功能
  const winSudoBin = "C:\\Windows\\System32\\sudo.exe";
  const winSudoAvaliable = fs.existsSync(winSudoBin);

  // 旧系统使用gsudo替代
  const gsudoBin = getAssetPath("thirdparty/gsudo/gsudo.exe");

  /**
   * 获取cmd-tools目录下的工具文件路径
   * @param name 工具名称
   */
  const getCmdTool = (name: string) => getAssetPath("cmd-tools", name);

  const spawn = (cmd: string, args?: string[]) => {
    return new Promise((resolve, reject) => {
      const proc = child_process.spawn(cmd, args || [], { windowsHide: true });
      let flag = false;

      proc.on("error", e => {
        if (flag) return;
        flag = true;
        reject(e);
      });

      let output = "";
      let errorOutput = "";
      proc.stdout.on("data", chunk => {
        output += iconv.decode(chunk, "gbk");
      });
      proc.stderr.on("data", chunk => {
        errorOutput += iconv.decode(chunk, "gbk");
      });
      proc.on("exit", () => {
        if (flag) return;
        flag = true;
        resolve({
          output,
          errorOutput,
        });
      });
    });
  };

  ipcMain.handle("cp.spawn", (_, cmd: string, args?: string[]) => {
    return spawn(cmd, args);
  });
  ipcMain.handle("cp.sudo", (_, cmd: string, args?: string[]) => {
    return winSudoAvaliable ? spawn(winSudoBin, ["--preserve-env", "--inline", cmd, ...(args || [])]) : spawn(gsudoBin, [cmd, ...(args || [])]);
  });
  ipcMain.handle("cp.execCmdTool", (_, cmd: string, args?: string[]) => {
    return spawn(getCmdTool(cmd), args);
  });
  ipcMain.handle("cp.sudo.execCmdTool", (_, cmd: string, args?: string[]) => {
    return winSudoAvaliable
      ? spawn(winSudoBin, ["--preserve-env", "--inline", getCmdTool(cmd), ...(args || [])])
      : spawn(gsudoBin, [getCmdTool(cmd), ...(args || [])]);
  });

  ipcMain.handle("cp.exec", (_, cmd: string, options: child_process.ExecOptions = {}) => {
    return new Promise((resolve, reject) => {
      child_process.exec(cmd, options, (error, stdout, stderr) => {
        if (error) {
          reject(error);
        } else {
          resolve({
            output: iconv.decode(Buffer.from(stdout), "GBK"),
            errorOutput: iconv.decode(Buffer.from(stderr), "GBK"),
          });
        }
      });
    });
  });

  ipcMain.handle("cp.execSudo", (_, cmd: string, options: child_process.ExecOptions = {}) => {
    return new Promise((resolve, reject) => {
      const sudo = winSudoAvaliable ? `${winSudoBin} --preserve-env --inline` : gsudoBin;
      child_process.exec(`${sudo} ${cmd}`, options, (error, stdout, stderr) => {
        if (error) {
          reject(error);
        } else {
          resolve({
            output: stdout,
            errorOutput: stderr,
          });
        }
      });
    });
  });

  ipcMain.handle("cp.execFile", (_, file: string, args?: string[], options?: child_process.ExecFileOptions) => {
    return new Promise((resolve, reject) => {
      child_process.execFile(file, args, options, (error, stdout, stderr) => {
        if (error) {
          reject(error);
        } else {
          resolve({
            output: stdout,
            errorOutput: stderr,
          });
        }
      });
    });
  });
})();
